package org.file5.dao.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.log4j.Logger;
import org.file5.dao.BaseDao;
import org.file5.dao.CategoryDao;
import org.file5.domain.BaseEntity;
import org.file5.domain.Category;
import org.file5.domain.Entity2Entity;
import org.file5.domain.Entity2Entity.Relation;
import org.file5.util.DataBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.appengine.api.datastore.QueryResultIterator;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;

@Repository("categoryDao")
public class CategoryDaoImpl implements CategoryDao {
	private final Logger logger = Logger.getLogger(this.getClass());
	public static int MAX_CATEGORY_LEVEL = 10;

	@Autowired
	BaseDao baseDao;

	@Override
	public DataBean<Category> getCategories(int startPosition, int maxResult,
			Object... params) {
		DataBean<Category> dataBean = new DataBean<Category>();

		Objectify ofy = ObjectifyService.begin();
		Query<Category> query = ofy.query(Category.class);

		String _pcategoryUid = null;
		// Category.Type _type = null;
		if (params != null) {
			for (Object o : params) {
				if (o instanceof String) {
					_pcategoryUid = (String) o;
				}

				// else if (o instanceof Category.Type) {
				// _type = (Category.Type) o;
				// }
			}
			if (_pcategoryUid == null || "".equals(_pcategoryUid)) {
				query.filter("primaryParentKey", null);
			} else {
				query.filter("primaryParentKey", new Key<Category>(
						Category.class, _pcategoryUid));
			}
			// if (_type != null) {
			// query.filter("type", _type.name());
			// }

		}

		dataBean.setCount(query.countAll());
		query.offset(startPosition).limit(maxResult);

		QueryResultIterator<Category> iterator = query.iterator();
		while (iterator.hasNext()) {
			dataBean.addDataE(iterator.next());
		}
		return dataBean;

	}

	@Override
	public List<Category> getPrimaryCategoryTrail(Key<Category> categoryKey) {

		List<Category> result = null;
		Category g = baseDao.find(Category.class, categoryKey);
		if (g != null) {
			result = new ArrayList<Category>(0);
			result.add(g);
			int i = 0;
			while (g.getPrimaryParentKey() != null && i < MAX_CATEGORY_LEVEL) {
				g = baseDao.find(Category.class, g.getPrimaryParentKey());
				if (g != null) {
					result.add(g);
				} else {
					break;
				}
				i++;
			}

			Collections.reverse(result);
		}
		return result;
	}

	@Override
	public <E extends BaseEntity> E addEntity2PrimaryCategoryTrail(
			Class<E> entityClass, E entity, Relation relation, Category category) {

		List<Category> gs = this.getPrimaryCategoryTrail(new Key<Category>(
				Category.class, category.getUid()));
		if (gs != null) {
			for (Category g : gs) {
				Entity2Entity<E, Category> e2g = baseDao.findEntity2Entity(
						entity, relation, category);
				if (e2g == null) {
					e2g = new Entity2Entity<E, Category>(entityClass, entity,
							relation, Category.class, category);
				}
				e2g.setStatus(entity.getStatus());
				Objectify ofy = ObjectifyService.begin();
				ofy.put(e2g);
			}
		}
		return entity;
	}

	@Override
	public DataBean<Category> getChildCategories(int startPosition,
			int maxResult, String categoryUid) {
		DataBean<Category> dataBean = new DataBean<Category>();

		Objectify ofy = ObjectifyService.begin();
		Query<Category> query = ofy.query(Category.class);

		query.filter("primaryParentKey", new Key<Category>(Category.class,
				categoryUid));

		dataBean.setCount(query.countAll());
		if (maxResult == -1) {
			query.offset(0).limit(query.countAll());
		} else {
			query.offset(startPosition).limit(maxResult);
		}

		QueryResultIterator<Category> iterator = query.iterator();
		while (iterator.hasNext()) {
			dataBean.addDataE(iterator.next());
		}
		return dataBean;
	}

}
